Skip to content

Rewrite ecs core - #74

Merged
SpectralDragon merged 83 commits into
mainfrom
feature/build_opt
Dec 9, 2025
Merged

SpectralDragon merged 83 commits into
mainfrom
feature/build_opt

Conversation

@SpectralDragon

@SpectralDragon SpectralDragon commented Jun 14, 2025 •

Copy link
Copy Markdown
Contributor

Update logic for storing and accessing components


Note

Massive refactor introducing chunk-based ECS with async queries/systems, revamped schedulers/resources, updated render graph/pipelines and Metal backend, reworked input/UI, and added extensive tests.

  • ECS Core:
    • Introduce chunk-based storage (Chunks, Chunk, ComponentLayout, BlobArray, SparseSet) and new Archetype model with edges.
    • Revamp queries and system params (WorldQueryTarget, QueryTarget, FilterQuery, SystemParameter, Ref, Res/ResMut), change detection via Tick.
    • Replace executors with protocol + single-threaded executor; simplify SystemsGraph; add System async update.
    • Overhaul World (entities/records, command queue, resources API, extract/spawn APIs, change tracking).
  • Schedulers:
    • Add/rename stages (extract, prepare, render, renderRunner, fixedUpdate removal/changes); new DefaultSchedulerRunner; async stage execution.
  • Rendering:
    • New command encoder layer (CommandBuffer, RenderCommandEncoder, Blit*); refactor Metal backend (swapchain/drawables, windows), remove old draw list paths.
    • Render graph becomes value type; new nodes for 2D (Main2DRenderNode, UpscaleNode); introduce pipeline configurators/cache (RenderPipelines).
    • Camera/render target rework (RenderViewTarget, viewport/texture handling); window surfaces management in render world.
  • Input/UI:
    • Input becomes Resource struct with rumble engine, event clearing system; update Apple gamepad manager to emit via callback.
    • UI systems updated; add UIRender scaffolding and window management resources.
  • Plugins:
    • Migrate plugins (Physics, RenderWorld, Sprite, Text, Camera, Tilemap, etc.) to new APIs/schedulers.
  • Utilities:
    • Add BlobArray, SparseSet, UnsafeBox, fixed-array/set helpers, hashing/util extensions.
  • Tests:
    • Add comprehensive ECS/storage/scheduler/world tests and utils tests (SparseArray/Set, hashing).

Written by Cursor Bugbot for commit 0a8887e. This will update automatically on new commits. Configure here.

@SpectralDragon

Copy link
Copy Markdown
Contributor Author

I need to stop..

cursor[bot]

This comment was marked as outdated.

Comment thread Sources/AdaECS/Entity/Entity.swift Outdated
Comment thread Sources/AdaSprite/SpriteRenderSystem.swift Outdated
Comment thread Sources/AdaECS/World/World.swift
Comment thread Sources/AdaEngineEmbeddable/ApplePlatforms/AEView.swift Outdated

ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Comment thread Sources/AdaECS/World/World.swift
Comment thread Sources/AdaECS/World/Chunks.swift
Comment thread Sources/AdaUI/DSL/ImageView.swift
Comment thread Sources/AdaRender/VisibleEntities.swift Outdated
Comment thread Sources/AdaECS/Query/Query.swift Outdated
Comment thread Sources/AdaECS/World/Chunks.swift
Comment thread Sources/AdaECS/Query/QueryTarget.swift
Comment thread Sources/AdaECS/System/System.swift
Comment thread Sources/AdaECS/Entity/Entity+ComponentSet.swift Outdated
Comment thread Sources/AdaECS/Query/Query.swift
Comment thread Sources/AdaECS/Query/Ref.swift Outdated
Comment thread Sources/AdaApp/AppBuilder.swift
Comment thread Sources/AdaECS/Query/ResQuery.swift
Comment thread Sources/AdaECS/Entity/Entity+ComponentSet.swift Outdated
Comment thread Sources/AdaApp/MainScheduler.swift Outdated
Comment thread Sources/AdaECS/Query/Query.swift
Comment thread Sources/AdaECS/Entity/Entity+ComponentSet.swift
Comment thread Sources/AdaECS/Entity/Entity+ComponentSet.swift Outdated
Comment thread Sources/AdaECS/Entity/Entity+ComponentSet.swift
Comment thread Sources/AdaECS/Commands/Commands.swift Outdated
Comment thread Sources/AdaECS/Commands/Commands.swift Outdated
Comment thread Assets/Examples/EmbeddableView/EmbeddableView/EmbeddableViewApp.swift Outdated
try await Self.processBatch(batch, state: state, operation: operation)
}
}
}

ghost Nov 29, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Parallel forEach silently swallows task errors

The forEach method uses await withThrowingTaskGroup without try, while the analogous map method correctly uses try await withThrowingTaskGroup and consumes results with for try await. When child tasks throw errors in forEach, those errors are silently lost because the task group body doesn't throw directly and results aren't consumed. This creates an inconsistency where map properly propagates errors but forEach does not.

Fix in Cursor Fix in Web

Vladislav Prusakov added 2 commits November 29, 2025 19:10
try await Self.processBatch(batch, state: state, operation: operation)
}
}
}

ghost Nov 29, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Parallel forEach silently drops errors from tasks

The forEach method uses await withThrowingTaskGroup without try, and doesn't iterate over task results. When a child task throws an error (e.g., when operation throws), the error is not propagated to the caller. Compare this to the map method on lines 71-83, which correctly uses try await withThrowingTaskGroup and iterates with for try await batchResults in group. The forEach implementation will silently swallow any errors thrown by the parallel operations, making debugging extremely difficult and potentially leaving the system in an inconsistent state.

Fix in Cursor Fix in Web

uses: maxim-lobanov/setup-xcode@v1.6.0
with:
xcode-version: '16.2.0'
xcode-version: '26.1.1'

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Invalid macOS and Xcode versions in CI workflows

The GitHub Actions workflow configuration specifies macos-26 runner and xcode-version: '26.1.1', which do not exist. As of late 2024, the latest available macOS runner is macos-15 (Sequoia) and the latest Xcode is 16.x. These invalid version references will cause all CI builds to fail immediately since GitHub cannot provision non-existent runner images.

Additional Locations (1)

Fix in Cursor Fix in Web

self.addedEntities.insert(entity.id)
if entity.id != Entity.notAllocatedId {
entities.addNotAllocatedEntity(entity)
}

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Inverted condition prevents entity ID allocation

The condition entity.id != Entity.notAllocatedId is inverted. When an entity is created with the public Entity(name:) constructor (which sets id = notAllocatedId) and added directly via world.addEntity(), the condition evaluates to false, so addNotAllocatedEntity is never called. This leaves the entity with an invalid ID of -25102018. The condition should be entity.id == Entity.notAllocatedId to properly allocate an ID for unallocated entities.

Fix in Cursor Fix in Web

xcode_version: ['16.2', '16.3']
runs-on: macos-15
xcode_version: ['26.1.1']
runs-on: macos-26

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Invalid CI runner and Xcode versions will break builds

The CI workflows were changed to use macos-26 runner and xcode-version: '26.1.1', which are non-existent versions. The previous valid values were macos-15 and '16.2.0'/'16.3'. GitHub Actions currently supports macos-13, macos-14, and macos-15 runners, and Xcode 26.1.1 does not exist. Given the PR discussion comment "I need to stop..", these appear to be placeholder or test values that were accidentally committed. All CI jobs will fail until these are reverted to valid versions.

Additional Locations (1)

Fix in Cursor Fix in Web

Comment thread Sources/AdaECS/Entity/Entity.swift Outdated
entity.components = self.components.copy()
entity.components.entity = entity
entity.components.entity = entity.id
entity.components.world = world

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Entity copy loses components due to unconditional didSet

The Entity.copy() method sets entity.components.world = world after copying components, but the didSet on ComponentSet.world unconditionally calls notFlushedComponents.removeAll(). This causes all copied components stored in notFlushedComponents to be lost. When copying an entity that hasn't been added to a world yet, the components are stored in notFlushedComponents, and this assignment clears them. For entities already in a world, the copied entity gets a world reference but uses notAllocatedId, making component lookups via world.get(from: entity) return nil since the world doesn't have that entity ID in its archetypes.

Additional Locations (1)

Fix in Cursor Fix in Web


public func update(context: inout UpdateContext) {
let result = self.fixedTimestep.advance(with: context.deltaTime)
@Res<DeltaTime?>

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Fixed update schedulers not created but still referenced

The FixedTimeSchedulerSystem references .fixedPreUpdate, .fixedUpdate, and .fixedPostUpdate schedulers in its order array and tries to run them via world.runScheduler(). However, MainSchedulerPlugin.setup only adds .fixed and .postUpdate schedulers, removing the old code that created these three fixed schedulers. When FixedTimeSchedulerSystem.update executes, it calls runScheduler for schedulers that don't exist, causing Schedulers.getScope to log "Scheduler not found" errors and skip execution. Systems added to these fixed schedulers won't run unless users manually add systems that auto-create them.

Additional Locations (1)

Fix in Cursor Fix in Web

xcode_version: ['16.2', '16.3']
runs-on: macos-15
xcode_version: ['26.1.1']
runs-on: macos-26

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: GitHub Actions workflow uses non-existent macOS and Xcode versions

The GitHub Actions workflows specify macos-26 and xcode-version: '26.1.1' which don't exist. GitHub Actions only supports up to macos-15 and Xcode versions up to 16.x as of late 2025. This appears to be a typo where "26" was written instead of "16". The CI/CD pipelines will fail immediately because these runner images don't exist.

Additional Locations (1)

Fix in Cursor Fix in Web


// Update entity components
// entity.components += counter.wrappedValue
// entity.components += textComponent.wrappedValue

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Performance counter text update disabled with print debugging

In PerformanceCounterSystem, the actual text rendering code is commented out (lines 377-378, 382, 385-386) while a print(text) debugging statement on line 381 remains active. The FPS counter will only output to console rather than displaying on screen. This appears to be debugging code that was accidentally left in.

Fix in Cursor Fix in Web

Comment thread Sources/AdaECS/Entity/Entity.swift Outdated
entity.components = self.components.copy()
entity.components.entity = entity
entity.components.entity = entity.id
entity.components.world = world

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Entity copy loses components when not in world

When copying an entity that hasn't been added to a world, all its components are lost. The copy() method first copies the ComponentSet (which includes notFlushedComponents), but then immediately sets entity.components.world = world. This triggers the didSet observer on the world property, which unconditionally calls notFlushedComponents.removeAll(). Since entities not yet in a world store their components in notFlushedComponents, copying such entities results in a copy with no components.

Fix in Cursor Fix in Web

xcode_version: ['16.2', '16.3']
runs-on: macos-15
xcode_version: ['26.1.1']
runs-on: macos-26

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: CI uses non-existent macOS and Xcode versions

The workflow files reference macos-26 and xcode-version: '26.1.1', which don't exist. Current macOS versions max out at 15 (Sequoia), and Xcode at 16.x. The previous valid values were macos-15 and 16.2.0. These invalid values will cause all CI builds to fail immediately. Given the PR comment "I need to stop..", these appear to be accidental placeholder or typo values.

Additional Locations (1)

Fix in Cursor Fix in Web

}
}
}
}

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Parallel forEach silently discards thrown errors

The forEach method is marked async rethrows and accepts a throwing operation, but uses await withThrowingTaskGroup instead of try await withThrowingTaskGroup. Since the body closure only adds tasks without throwing, and there's no iteration over group results (unlike the map method which correctly uses for try await), any errors thrown by the operation inside child tasks will be silently discarded rather than propagated to the caller.

Fix in Cursor Fix in Web


public func update(context: inout UpdateContext) {
let result = self.fixedTimestep.advance(with: context.deltaTime)
@Res<DeltaTime?>

ghost Dec 1, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Fixed-time schedulers referenced but never registered

FixedTimeSchedulerSystem attempts to run schedulers .fixedPreUpdate, .fixedUpdate, and .fixedPostUpdate, but these are never registered with the world. The MainSchedulerPlugin.setup only registers .main, .fixed, and .postUpdate schedulers. The old code explicitly added the fixed-time schedulers but this registration was removed during the refactor while the system still references them.

Additional Locations (1)

Fix in Cursor Fix in Web

Comment thread Sources/AdaECS/Entity/Entity.swift Outdated
entity.components = self.components.copy()
entity.components.entity = entity
entity.components.entity = entity.id
entity.components.world = world

ghost Dec 4, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Entity copy loses all components when setting world

The Entity.copy() method copies the ComponentSet including its notFlushedComponents, then sets entity.components.world = world. However, the world property has a didSet observer that calls self.notFlushedComponents.removeAll(). This means all copied components are immediately discarded after being copied, resulting in an empty entity. The copied entity loses all its component data.

Additional Locations (1)

Fix in Cursor Fix in Web

resource[keyPath: keyPath] = value
worlds.insertResource(resource)
let resource = worlds.main.getRefResource(T.self)
resource.wrappedValue[keyPath: keyPath] = value

ghost Dec 4, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: updateResource crashes when resource doesn't exist in world

The updateResource modifier now calls getRefResource(T.self) which creates a Ref that can have a nil internal pointer when the resource doesn't exist. Accessing wrappedValue on this Ref force-unwraps the nil pointer, causing a crash. The previous implementation used a guard statement with getResource to safely handle missing resources. This regression will crash if updateResource is called before the resource is inserted into the world.

Fix in Cursor Fix in Web

// container.foregroundColor = .white

let text = "Bunnies: \(bunnyCount)\nFPS: \(String(format: "%.1f", counter.fps))"
print(text)

ghost Dec 6, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Debug print statement outputs every frame

The print(text) statement inside PerformanceCounterSystem.update outputs FPS and bunny count every single frame, which will flood the console during runtime. This appears to be debug code that was left in, as evidenced by the commented-out lines nearby that would properly update the text component instead.

Fix in Cursor Fix in Web

}

print()
}

ghost Dec 6, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Test code left in example application

The Kek component and TestPlugin struct appear to be debug/test code that was accidentally committed. The TestPlugin is commented out in the app initialization but the code still exists, including print() statements that would output test data. The PR author's comment "I need to stop.." suggests this may be work-in-progress code that shouldn't be committed.

Fix in Cursor Fix in Web


public var isEmpty: Bool {
commands.isEmpty
}

ghost Dec 6, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Data race in WorldCommandQueue isEmpty property

The isEmpty property and copy() method in WorldCommandQueue read commands without acquiring the lock, while push() uses locking. Additionally, applyAndDrop() mutates commands via popFirst() without locking. Since this class is marked @unchecked Sendable, these unprotected accesses can cause data races when the queue is accessed from multiple threads.

Additional Locations (2)

Fix in Cursor Fix in Web

self.buffer = other.buffer
self.bitset = other.bitset
self.entity = other.entity
self.notFlushedComponents = other.notFlushedComponents

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Entity copy loses all components from world-bound entities

The ComponentSet.init(from:) copy constructor copies notFlushedComponents but doesn't copy the world reference. When an entity is added to a world, its components are flushed to archetype storage and notFlushedComponents is cleared (via the didSet on line 25). When Entity.copy() is called on a world-bound entity, the copied ComponentSet has no world reference and empty notFlushedComponents, resulting in all component data being lost.

Additional Locations (1)

Fix in Cursor Fix in Web

jobs:
build-and-deploy-docs:
runs-on: macos-15
runs-on: macos-26

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: GitHub Actions uses non-existent macos-26 runner image

The GitHub Actions workflow specifies runs-on: macos-26 which is not a valid runner image. The latest available macOS runner is macos-15. This will cause CI builds to fail as the runner cannot be provisioned.

Additional Locations (1)

Fix in Cursor Fix in Web

var container = TextAttributeContainer()
container.foregroundColor = .white

let text = unsafe "Bunnies: \(bunnyCount)\nFPS: \(String(format: "%.1f", counter.fps))"

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Misplaced unsafe keyword before string literal

The unsafe keyword is incorrectly placed before a string literal expression (unsafe "Bunnies: ..."). In Swift's strict memory safety mode, unsafe is used to mark expressions involving pointer operations or other unsafe APIs, not regular string interpolation. This appears to be accidentally committed code that should be removed.

Fix in Cursor Fix in Web

container.foregroundColor = .white

let text = unsafe "Bunnies: \(bunnyCount)\nFPS: \(String(format: "%.1f", counter.fps))"
print(text)

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Debug print statement left in production example code

A print(text) statement is called every frame in the PerformanceCounterSystem.update() method, logging bunny count and FPS to the console. This debug output will significantly impact performance and clutter logs in a stress test example meant to benchmark rendering performance.

Additional Locations (1)

Fix in Cursor Fix in Web

public extension Commands {
func append(_ commands: Commands) {
self.queue.commands.append(contentsOf: commands.queue.commands)
}

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Race condition in WorldCommandQueue concurrent access

The WorldCommandQueue class uses a lock in push() for thread safety, but the append() method directly accesses self.queue.commands without acquiring the lock. Similarly, applyAndDrop(), copy(), and isEmpty don't use the lock. Since the class is marked @unchecked Sendable and push() is designed to be called from any thread, concurrent access between locked and unlocked operations on the internal Deque can cause data corruption or crashes.

Fix in Cursor Fix in Web


public var isLoaded: Bool {
self.asset == nil
}

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: isLoaded property returns inverted boolean value

The isLoaded property in AssetHandle returns self.asset == nil, which is the opposite of the intended meaning. When asset is nil, the asset is not loaded, so isLoaded would incorrectly return true. The condition is reversed and likely meant to be self.asset != nil.

Fix in Cursor Fix in Web

uses: maxim-lobanov/setup-xcode@v1.6.0
with:
xcode-version: '16.2.0'
xcode-version: '26.1.1'

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: GitHub workflow uses non-existent macOS and Xcode versions

The CI workflows changed from macos-15 to macos-26 and Xcode from 16.2.0/16.3 to 26.1.1. Combined with the PR comment "I need to stop..", these appear to be accidental test/debug values. While macOS 26 and Xcode 26 may exist as future releases, using them in CI will likely cause workflow failures until these runners are available on GitHub Actions.

Additional Locations (1)

Fix in Cursor Fix in Web

self.queue.push { [entityId] world in
world.removeEntity(entityId)
}
}

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: recursively parameter is ignored in removeFromWorld

The EntityCommands.removeFromWorld(recursively:) method accepts a recursively parameter but never uses it. The call to world.removeEntity(entityId) doesn't pass the recursively flag, so child entities will never be removed even when recursively: true is specified. This could cause orphaned entities or unexpected behavior when callers expect recursive removal.

Fix in Cursor Fix in Web


public var isLoaded: Bool {
self.asset == nil
}

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Inverted logic in isLoaded property returns wrong value

The isLoaded computed property in AssetHandle returns self.asset == nil, which means it returns true when the asset is NOT loaded and false when it IS loaded. This is the opposite of what the property name suggests. The logic should be self.asset != nil to correctly indicate whether the asset has been loaded.

Fix in Cursor Fix in Web

uses: maxim-lobanov/setup-xcode@v1.6.0
with:
xcode-version: '16.2.0'
xcode-version: '26.1.1'

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: GitHub CI uses non-existent macOS and Xcode versions

The CI workflows specify macos-26 runner and Xcode 26.1.1, which are non-existent versions. GitHub Actions runners currently support up to macos-15. These appear to be placeholder or future versions that were accidentally committed and will cause CI failures. The previous values were macos-15 and Xcode 16.2.0/16.3.

Additional Locations (1)

Fix in Cursor Fix in Web

container.foregroundColor = .white

let text = unsafe "Bunnies: \(bunnyCount)\nFPS: \(String(format: "%.1f", counter.fps))"
print(text)

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Debug print statement left in performance counter system

The PerformanceCounterSystem contains a print(text) statement that outputs FPS and bunny count to the console on every frame when the counter updates. This debug statement will cause excessive console spam during runtime and should be removed from production code.

Additional Locations (1)

Fix in Cursor Fix in Web


print()
}
}

ghost Dec 8, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Debug code "Kek" component and TestPlugin left in

The file contains debugging artifacts: a Kek component (with a non-descriptive name storing a World reference) and a TestPlugin that spawns 100 entities and prints debug output. These appear to be test code that was accidentally left in and should be removed before merging.

Fix in Cursor Fix in Web

Comment thread Sources/AdaAudio/AudioPlugin.swift

public var isLoaded: Bool {
self.asset == nil
}

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Inverted logic in isLoaded property check

The isLoaded computed property returns true when self.asset == nil, which is the opposite of the expected behavior. An asset handle is loaded when its asset is NOT nil. The condition should be self.asset != nil to correctly indicate that the asset has been loaded.

Fix in Cursor Fix in Web

xcode_version: ['16.2', '16.3']
runs-on: macos-15
xcode_version: ['26.1.1']
runs-on: macos-26

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Invalid CI runner and Xcode version configuration

The GitHub Actions workflows reference macos-26 runner and Xcode version 26.1.1, which do not currently exist on GitHub Actions. The latest available macOS runner is macos-15, and while Xcode 26 betas may exist, the specific version 26.1.1 and the macos-26 runner image are not available, causing CI builds to fail.

Additional Locations (1)

var container = TextAttributeContainer()
container.foregroundColor = .white

let text = unsafe "Bunnies: \(bunnyCount)\nFPS: \(String(format: "%.1f", counter.fps))"

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Misplaced unsafe keyword before string literal

The unsafe keyword is incorrectly placed before a string literal (unsafe "Bunnies..."). In Swift, unsafe is used for memory operations and pointer access, not for string interpolation expressions. This appears to be accidentally committed code that will likely cause a compilation error or unexpected behavior.

Fix in Cursor Fix in Web

@SpectralDragon
SpectralDragon merged commit 68a93f9 into main Dec 9, 2025
container.foregroundColor = .white

let text = unsafe "Bunnies: \(bunnyCount)\nFPS: \(String(format: "%.1f", counter.fps))"
print(text)

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Debug print statement floods console every frame

A print(text) statement inside PerformanceCounterSystem.update() will execute every frame, flooding the console with bunny count and FPS output. This appears to be debug code that was accidentally left in the stress test example.

Fix in Cursor Fix in Web

self.asset = asset as! T
self.type = try container.decode(String.self, forKey: .type)
self.assetPath = try container.decode(String.self, forKey: .assetPath)
self.assetMeta = try container.decode(AssetMetaInfo.self, forKey: .meta)

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Decoded AssetHandle has nil asset causing potential crashes

The init(from decoder:) method never initializes the asset property, leaving it nil. Since asset is declared as an implicitly unwrapped optional (T!), any code that decodes an AssetHandle and accesses asset without first checking isLoaded or calling load() will crash. The previous implementation ensured asset was always non-nil after construction.

Additional Locations (1)

Fix in Cursor Fix in Web

jobs:
build-and-deploy-docs:
runs-on: macos-15
runs-on: macos-26

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: CI uses non-existent macOS 26 GitHub Actions runner

The workflows specify runs-on: macos-26 and xcode-version: '26.1.1'. While macOS 26 (Tahoe) and Xcode 26 exist as Apple products, GitHub Actions macos-26 runner may not be available yet. The previous values (macos-15 and Xcode 16.2.0/16.3) were valid. CI builds will fail if this runner doesn't exist.

Additional Locations (1)

Fix in Cursor Fix in Web

while let drop = commands.popFirst() {
drop.applyToWorld(world)
}
}

ghost Dec 9, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Race condition in WorldCommandQueue due to inconsistent locking

WorldCommandQueue is marked @unchecked Sendable but has inconsistent thread safety. The push() method acquires the lock before modifying commands, but isEmpty, copy(), and applyAndDrop() all access commands without locking. If commands are pushed from one thread while being processed or read on another, this causes a data race on the Deque.

Fix in Cursor Fix in Web

@SpectralDragon
SpectralDragon deleted the feature/build_opt branch December 14, 2025 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant